package org.bjf.modules.sys.web.controller;

import static org.bjf.modules.sys.listenner.LiveBeanPostProcessor.PERMISSION_MAP;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.bjf.modules.core.web.core.PageVO;
import org.bjf.modules.sys.bean.ControllerResource;
import org.bjf.modules.sys.bean.SysAcl;
import org.bjf.modules.sys.bean.SysMenu;
import org.bjf.modules.sys.bean.SysRole;
import org.bjf.modules.sys.enums.AclEnum.ResourceType;
import org.bjf.modules.sys.query.SysMenuQuery;
import org.bjf.modules.sys.query.SysRoleQuery;
import org.bjf.modules.sys.service.SysAclService;
import org.bjf.modules.sys.service.SysMenuService;
import org.bjf.modules.sys.service.SysRoleService;
import org.bjf.modules.sys.web.vo.MenuVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("admin")
public class SysRoleController {

  @Autowired
  private SysRoleService roleService;
  @Autowired
  private SysMenuService menuService;
  @Autowired
  private SysAclService aclService;

  @RequestMapping("role/detail")
  public SysRole detail(@RequestParam long sysRoleId) {
    return roleService.get(sysRoleId);
  }

  @RequestMapping("role/list")
  public List<SysRole> list(SysRoleQuery query) {
    return roleService.list(query);
  }

  @RequestMapping("role/listPage")
  public PageVO<SysRole> listPage(SysRoleQuery query) {
    return roleService.listPage(query);
  }

  @RequestMapping("role/listAll")
  public List<SysRole> listAll(SysRoleQuery query) {
    return roleService.listAll(query);
  }


  @RequestMapping("role/add")
  public void add(@Validated SysRole role) {
    roleService.add(role);
  }

  @RequestMapping("role/update")
  public void update(@Validated SysRole role) {
    roleService.updateById(role);
  }

  @RequestMapping("role/delete")
  public void delete(@RequestParam long sysRoleId) {
    roleService.deleteById(sysRoleId);
  }


  /**
   * 查询角色的权限列表
   */
  @RequestMapping("role/list-permission")
  public Collection<ControllerResource> listPermission(@RequestParam Long roleId) {
    //===1.查询acl权限
    List<SysAcl> aclList = aclService.listRolePermission(roleId, ResourceType.CONTROLLER, null);
    Map<String, SysAcl> aclMap = aclList.stream()
        .collect(Collectors.toMap(SysAcl::getResourceId, e -> e));

    //===2.返回权限列表
    Collection<ControllerResource> resources = PERMISSION_MAP.values();
    for (ControllerResource resource : resources) {
      if (aclMap.containsKey(resource.getResSn())) {
        SysAcl acl = aclMap.get(resource.getResSn());
        String bin = Integer.toBinaryString(acl.getAclState());
        resource.setAcl(StringUtils.leftPad(bin, 4, "0"));
      }
    }

    return resources;
  }

  /**
   * 全量更新角色权限
   */
  @RequestMapping("role/update-permission/{roleId}")
  public void updatePermission(@PathVariable long roleId,
      @RequestBody List<ControllerResource> resources) {
    roleService.updateControllerPermission(roleId, resources);
  }

  /**
   * 查询角色菜单列表(返回所有菜单，标记是否有分配权限)
   */
  @RequestMapping("role/list-menu")
  public List<MenuVo> listMenu(@RequestParam Long roleId) {
    //===1.查询所有菜单
    List<SysMenu> allMenu = menuService.listAll(new SysMenuQuery());

    //===2.查询角色菜单
    Map<Long, Integer> roleMenuMap = roleService.listMenu(roleId)
        .stream()
        .collect(Collectors.toMap(SysMenu::getSysMenuId, e -> 1));
    List<MenuVo> list = new ArrayList<>();

    //===3.设置菜单是否分配给角色的标记
    for (SysMenu menu : allMenu) {
      MenuVo vo = new MenuVo();
      BeanUtils.copyProperties(menu, vo);
      if (roleMenuMap.containsKey(menu.getSysMenuId())) {
        vo.setAssigned(1);
      }
      list.add(vo);
    }

    return list;
  }

  /**
   * 给角色分配菜单
   */
  @RequestMapping("role/update-menu")
  public void updateMenu(@RequestParam Long roleId, @RequestParam String menuIds) {
    roleService.updateMenu(roleId, menuIds);
  }
}
